package gradle.common.feign.config.feign;

import feign.RequestInterceptor;
import feign.RequestTemplate;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 为什么不能放在 Gateway 模块？
 * Feign 拦截器的作用域：
 * Feign 拦截器是绑定到具体 Feign 客户端的，而 Gateway 不直接发起 Feign 调用（它通过路由转发 HTTP 请求）。
 * 请求上下文问题：
 * Gateway 的 GlobalFilter 可以访问原始请求的上下文（如 HttpServletRequest），但 Feign 拦截器需要访问发起 Feign 调用的服务的上下文，这两者是不同的。
 * <p>
 * <p>
 * 完整流程示例
 * 以 service-a 调用 service-b 为例：
 * <p>
 * 客户端 → Gateway：
 * 客户端发送请求 GET /api/data，携带 Authorization: Bearer <token>。
 * Gateway 通过 GlobalFilter 提取 Token 并转发到 service-a（通过 X-Forwarded-Token 头）。
 * Gateway → Service-A：
 * Gateway 将请求路由到 service-a，并携带 X-Forwarded-Token 头。
 * Service-A → Service-B：
 * service-a 的 Feign 拦截器从当前请求的 X-Forwarded-Token 头中提取 Token，并添加到 Feign 请求的头中（如 Authorization: Bearer <token>）。
 * service-b 接收请求并验证 Token。
 * <p>
 * <p>
 * <p>
 * 关键原则：
 * <p>
 * Feign 拦截器 → 放在发起 Feign 调用的服务模块中。
 * <p>
 * 1.Token 转发 → 在 Gateway 中用 GlobalFilter
 * 2.在服务间调用时用 RequestInterceptor。
 *
 * @author 1141193930@qq.com
 */
public class FeignTokenRelayInterceptor implements RequestInterceptor {


    @Override
    public void apply(RequestTemplate template) {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if(null==attributes){
            return;
        }
        HttpServletRequest request = attributes.getRequest();

        // 从当前请求的上下文中获取 Token（如 HttpServletRequest）
        String token = request.getHeader(HttpHeaders.AUTHORIZATION);
        //set token
        if (StringUtils.isNotBlank(token)) template.header(HttpHeaders.AUTHORIZATION, token);
    }
}